package org.bookshare.validator;

import java.io.File;
import java.io.IOException;

import org.benetech.event.EventListener;
import org.benetech.event.LoggingEventListener;
import org.benetech.util.FileUtils;
import org.bookshare.document.beans.DocumentSet;
import org.bookshare.document.beans.DocumentType;
import org.bookshare.document.beans.NIMASDocumentSet;
import org.bookshare.document.reader.NIMASReader;
import org.bookshare.document.reader.Reader;
import org.bookshare.validator.report.HTMLReportEngine;
import org.bookshare.validator.report.ReportEngine;
import org.bookshare.validator.report.ValidationMetadata;
import org.bookshare.validator.rule.OPFMetadataRule;
import org.bookshare.validator.rule.ResourcesExistRule;
import org.bookshare.validator.rule.Rule;
import org.bookshare.validator.rule.XMLDocumentsParseRule;
import org.bookshare.validator.rule.XMLPageNumbersRule;

/**
 * Validate a NIMAS file. The file passed in must be a zip.
 *
 * @author Reuben Firmin
 */
public class NIMASValidator implements Validator<DocumentType.NIMAS> {

    /** The list of rules to run. This could be a user configurable option */
    private static final Rule[] RULES = new Rule[] {
    	// must come first
    	new XMLDocumentsParseRule(),
        new ResourcesExistRule(),
        new OPFMetadataRule(),
        new XMLPageNumbersRule(),
    };

    /**
     * Default constructor.
     */
    public NIMASValidator() {
    	//empty
    }

    /**
     * {@inheritDoc}
     */
    public final ValidationMetadata validate(final DocumentSet<DocumentType.NIMAS> documentSet, final EventListener listener)
        throws IOException
    {
        if (documentSet == null) {
            throw new IOException("Null document set!");
        }

        if (!(documentSet instanceof NIMASDocumentSet)) {
            throw new IOException("Unable to validate documents of type: "
                    + documentSet.getType());
        }

        // reporting object
        final ValidationMetadata reportMetadata = new ValidationMetadata("NIMAS");

        reportMetadata.setDocumentSet((NIMASDocumentSet) documentSet);

        listener.message("Automated Checks");
        // now run the list of rules we have
        for (Rule rule : RULES) {
            listener.message("Evaluating rule: " + rule.getClass().getName());
            rule.evaluate(reportMetadata, listener);
        }

        return reportMetadata;
    }

    /**
     * {@inheritDoc}
     */
    public static void main(final String[] args) {
        if (args.length < 2) {
            System.out.println("Usage: java org.benetech.validator.nimas.NIMAS"
                    + "Validator package.zip myReportName");
            System.exit(1);
        }
        final String zipFileName = args[0];
        final String reportFileName = args[1];
        final File zipFile = new File(zipFileName);
        if (!zipFile.exists()) {
            System.out.println("Package file " + zipFile + " not found.");
            System.exit(1);
        }

        try {
            final EventListener listener = new LoggingEventListener("NIMAS");
            final Reader<DocumentType.NIMAS> reader = new NIMASReader();
            reader.setTmpDir(FileUtils.getTmpDir().getAbsolutePath());
            final DocumentSet<DocumentType.NIMAS> documentSet = reader.read(zipFile, listener);
            final NIMASValidator validator = new NIMASValidator();
            final ValidationMetadata report = validator.validate(documentSet, listener);
            final ReportEngine engine = new HTMLReportEngine();
            listener.message("======> Generating report");
            engine.generateReport(new File("."), reportFileName,
                    report, listener);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(2);
        }
     }
}
